/*
 *
 *
 */

#include "Sprite.h"

#ifndef _SPRITE_CPP_
#define _SPRITE_CPP_


/*
 * 
 */
Sprite::Sprite(void)
{
    angle = 0;
    zoom = 1;
    x = 0;
    y = 0;
    surface = NULL;
    surfaceRotoZoom = NULL;
    rectangle.x = 0; 
    rectangle.y = 0; 
    rectangle.w = 0; 
    rectangle.h = 0;             
    rectRotoZoom.x = 0;
    rectRotoZoom.y = 0;
    rectRotoZoom.w = 0;
    rectRotoZoom.h = 0;
}

/*
 * 
 */ 
Sprite::Sprite(const Sprite& sprite)
{
    this->fileName = sprite.fileName;
    angle = sprite.angle;
    zoom = sprite.zoom;
    x = sprite.x;
    y = sprite.y;
    rectangle = sprite.rectangle; 
    rectRotoZoom = sprite.rectRotoZoom;
    surface = NULL;
    surfaceRotoZoom = NULL;
}

/*
 *
 */
Sprite::Sprite(string fileName, double x, double y)
{
    this->fileName = fileName;
    this->x = x;
    this->y = y;
    angle = 0;
    zoom = 1;
    surfaceRotoZoom = NULL;
    if((surface = IMG_Load(this->fileName.c_str()))== NULL)	/*string.c_str() retorna um char equivalente a string*/
        fprintf(stderr,"Erro no metodo \"Sprite::Sprite(string fileName, int x, int y)\" ao carregar arquivo de Sprite %s %s\n",this->fileName.c_str(), IMG_GetError());
    else
    {
        rectangle.x = x;
        rectangle.y = y;
        rectangle.w = surface->w;
        rectangle.h = surface->h;
    }
}

/*
 * 
 */
Sprite & Sprite::operator=(const Sprite &sprite)
{
    if (this == &sprite) 
        return *this;
    else 
    {
        fileName = sprite.fileName;
        angle = sprite.angle;
        zoom = sprite.zoom;
        x = sprite.x;
        y = sprite.y;
        rectangle = sprite.rectangle; 
        rectRotoZoom = sprite.rectRotoZoom;

        if((surface = IMG_Load(this->fileName.c_str()))== NULL)	/*string.c_str() retorna um char equivalente a string*/
            fprintf(stderr,"Erro no metodo \"Sprite & Sprite::operator=(const Sprite &sprite)\" ao carregar arquivo de Sprite %s %s\n",this->fileName.c_str(),IMG_GetError());
    }
    return *this;
}

/*
 *
 */
Sprite::~Sprite(void)
{
    if(surface != NULL)
        SDL_FreeSurface(surface);
    if(surfaceRotoZoom != NULL)
        SDL_FreeSurface(surfaceRotoZoom);
}

/*
 * 
 */
void Sprite::render(SDL_Surface *screen)
{
    if((angle == 0) && (zoom == 1))
    {
        rectangle.x = (int) x /*- rectangle.w/2*/;
        rectangle.y = (int) y /*- rectangle.h/2*/;
        if(SDL_BlitSurface(surface, NULL, screen, &rectangle))
            fprintf(stderr,"Erro ao blitar imagem no metodo void Sprite::render(SDL_Surface *screen): %s\n%s\n", fileName.c_str(),SDL_GetError());
    }
    else
    {
        rectRotoZoom.x = (int) x /*- rectRotoZoom.w/2*/;
        rectRotoZoom.y = (int) y /*- rectRotoZoom.h/2*/;
        if(SDL_BlitSurface(surfaceRotoZoom, NULL, screen, &rectRotoZoom))
            fprintf(stderr,"Erro ao blitar imagem rotacionada no metodo void Sprite::render(SDL_Surface *screen): %s\n%s\n", fileName.c_str(),SDL_GetError());
    }
}

/*
 *
 */
void Sprite::updatePos(double x, double y)
{
    this->x = x;
    this->y = y;
}

/*
 *
 */
SDL_Rect Sprite::getRect(void)
{
    if((angle == 0) && (zoom == 1))
    {
        rectangle.x = (int) x /*- rectangle.w/2*/;
        rectangle.y = (int) y /*- rectangle.h/2*/;
        return rectangle;
    }
    else
    {
        rectRotoZoom.x = (int) x /*- (rectRotoZoom.w/2)*/;
        rectRotoZoom.y = (int) y /*- (rectRotoZoom.h/2)*/;
        return rectRotoZoom;
    }
}

/*
 * 
 */ 
bool Sprite::boxCollidesWith(Sprite *sprite)
{
    float diffx, diffy;
    SDL_Rect spriteRect;
    spriteRect = sprite->getRect();
    diffx = x - spriteRect.x;
    diffy = y - spriteRect.y;
    
    if((diffx > spriteRect.w) || (-diffx > rectangle.w))
        return false;
    else if((diffy > spriteRect.h) || (-diffy > rectangle.h))
        return false;
    else
       return true;
    
}

/*
 * 
 */ 
bool Sprite::sphereCollidesWith(Sprite *sprite)
{
    SDL_Rect spriteRect = sprite->getRect();
    SDL_Rect thisRect = getRect();
    /*o raio sera a metade da maior dimensão da sprite*/
    int spriteRadius = (spriteRect.w > spriteRect.h) ? spriteRect.w/2 : spriteRect.h/2;
    int thisRadius = (thisRect.w > thisRect.h) ? thisRect.w/2 : thisRect.h/2;
    int dx = (thisRect.x + thisRadius) - (spriteRect.x + spriteRadius);
    int dy = (thisRect.y + thisRadius) - (spriteRect.y + spriteRadius);
    
    return (sqrt(pow(dx, 2) + pow(dy, 2)) <= (spriteRadius + thisRadius));
}

/*
 * 
 */ 
void Sprite::setZoom(double zoom)
{
    this->zoom = zoom;
    if(surfaceRotoZoom != NULL)
    {
        SDL_FreeSurface(surfaceRotoZoom);
        surfaceRotoZoom = NULL;
    }
    if((surfaceRotoZoom = rotozoomSurface(surface, angle, this->zoom, 1)) == NULL)
        fprintf(stderr,"Erro ao dar Zoom na Sprite %s\n%s\n",fileName.c_str(),SDL_GetError());
    rectRotoZoom.x = (float) x;
    rectRotoZoom.y = y;
    rectRotoZoom.w = surfaceRotoZoom->w;
    rectRotoZoom.h = surfaceRotoZoom->h;
}

/*
 * 
 */
void Sprite::setRot(double angle)
{
    this->angle = angle;
    if(surfaceRotoZoom != NULL)
    {
        SDL_FreeSurface(surfaceRotoZoom);
        surfaceRotoZoom = NULL;
    }
    if((surfaceRotoZoom = rotozoomSurface(surface, this->angle, zoom, 1)) == NULL)
        fprintf(stderr,"Erro ao rotacionar Sprite %s\n%s\n",fileName.c_str(),SDL_GetError());
    rectRotoZoom.x = (int) x;
    rectRotoZoom.y = (int) y;
    rectRotoZoom.w = surfaceRotoZoom->w;
    rectRotoZoom.h = surfaceRotoZoom->h;
}



#endif
